local UserBaseInfo = require("app.public.dao.UserBaseInfo")
local FileUtils = cc.FileUtils:getInstance()
local FileUtils_isFileExist = FileUtils.isFileExist

local EntityModel = class("EntityModel")

local AvatarFactotry = require("app.public.avatar.AvatarFactory")

local string_format = string.format

EntityModel.__eq = function(t1,t2)
    return t1.protoUnit.unitModelId == t2.protoUnit.unitModelId
end

function EntityModel.create(id, protoUnit, myTeamId, isTimeMonster, isSummon, isRefresh, isKof)
    local model = EntityModel.new()
    model.id = id
    model.protoUnit = protoUnit
    model.myTeamId = myTeamId
    model.isTimeMonster = isTimeMonster
    model.isSummonEntity = isSummon --是否为召唤model
    model.isRefreshEntity = isRefresh --是否为刷新怪
    model.isKofEntity = isKof --是否为kof后续替换

    local userBaseInfo = UserBaseInfo.new()
    userBaseInfo:read(protoUnit.userBaseInfo)
    model.userBaseInfo = userBaseInfo

    model.kind = protobuf.enum_id("battle2.EUnitKind", protoUnit.kind)
--    model.unitModelId = protoUnit.unitModelId
    model.npcKind = protobuf.enum_id("battle2.ENpcKind", protoUnit.npcKind)
--    model.npcId = protoUnit.npcId
    model.isRolePlay = protoUnit.isRolePlay
    -- 竞技场、冠军赛添加阵营时装
    if not protoUnit.isRolePlay and
      model.kind == Enums.UnitType.Player and
      BattleManager:isBattleUsingArenaAvatar() then
        local isMember = protoUnit.teamId == myTeamId
        local fashionIds = GD:getArenaFashionIds(protoUnit.userBaseInfo.gender, protoUnit.userBaseInfo.classID, isMember)
        model.fashionIDs = GD:attachArenaFashionIds(protoUnit.userBaseInfo.fashionIDs, fashionIds)
    else
        model.fashionIDs = protoUnit.userBaseInfo.fashionIDs
    end

--    model.rangeVision = protoUnit.rangeVision
--    model.pos = protoUnit.location
    local dir = protoUnit.faceDir
    if dir == Enums.Face.left then
        --面朝左
        model.dir = -1
    elseif dir == Enums.Face.right then
        --面朝右
        model.dir = 1
    end

    model.teamId = protoUnit.teamId
    model.isLeader = protoUnit.isLeader
    model.canRevive = protoUnit.canRevive --是否为可复活
    model.isFakeNpc = protoUnit.fakeNpc == 1
    model.isNeutral = protoUnit.isNeutral
    model.interactionType = protoUnit.interactionType or 0
--    model.isCrucial = protoUnit.isCrucial
    model.buildingType = protoUnit.buildingType
    model.hideHead = protoUnit.hideHead
    model.specialHPMax = protoUnit.specialHPMax
    model.specialistID = protoUnit.userBaseInfo.specialistID
    model.relatedNpcId = protoUnit.relatedNpcId

    model.skills = {}

    model.name = L(protoUnit.userBaseInfo.name) or string.format("%d", model.protoUnit.unitModelId)
    model.defaultZOrder = 0
    model.height = 0
    model.size = 500
    model.deathSound = model:getDeathSound()
    model.isShowMana = model:getIsShowMana()
    model.selectSize = model:getSelectSize()
    model.selectExcursion = model:getSelectExcursion()
    model.sfxPath = model:getSfxPath()

    return model
end

function EntityModel:ctor()
    cc(self):addComponent("components.behavior.SimpleEvent"):exportMethods()
end

function EntityModel:getId()
    return self.id
end

function EntityModel:getUnitModelId()
    return self.protoUnit.unitModelId
end

function EntityModel:getUid()
    return self.userBaseInfo:getUid()
end

function EntityModel:getTeamId()
    return self.teamId
end

function EntityModel:getPos()
    return self.protoUnit.location
end

function EntityModel:getDir()
    return self.dir
end

function EntityModel:getDefaultZOrder()
    return self.defaultZOrder
end

function EntityModel:getSize()
    return self.size
end

function EntityModel:getHeight()
    return self.height
end

function EntityModel:getIsTimeMonster()
    return self.isTimeMonster
end

function EntityModel:getSpecialHPMax()
    return self.specialHPMax
end

-- 是和我一组的成员
function EntityModel:isInMyTeam()
    return self.teamId == self.myTeamId
end

function EntityModel:isElite()
    return self.kind == Enums.UnitType.Npc and self.npcKind == Enums.NpcKind.NpcKind_Elite
end

function EntityModel:setKind(kind)
    self.kind = kind
end

function EntityModel:getKind()
    return self.kind
end

function EntityModel:setNpcKind(npcKind)
    self.npcKind = npcKind
end

function EntityModel:getNpcKind()
    return self.npcKind
end

function EntityModel:setIsLeader(flag)
    self.isLeader = flag
end

function EntityModel:getIsLeader()
    return self.isLeader
end

function EntityModel:getIsFakeNpc()
    return self.isFakeNpc
end

function EntityModel:getIsNeutral()
    return self.isNeutral
end

function EntityModel:isHidingHead()
    return self.hideHead == 1
end

function EntityModel:canInteractWith()
    return self.interactionType > 0
end

function EntityModel:getSpecialistID()
    return self.specialistID
end

function EntityModel:hasRelatedNpc()
    return self.relatedNpcId ~= 0
end

function EntityModel:setRelatedNpcId(npcId)
    self.relatedNpcId = npcId
end

function EntityModel:getRelatedNpcId()
    return self.relatedNpcId
end

function EntityModel:getProtoSkills()
    return self.protoUnit.skills
end

function EntityModel:isOriginalEntity()
    return (not self.isSummonEntity) and (not self.isRefreshEntity) and (not self.isKofEntity)
end

function EntityModel:getLv()
    return self.protoUnit.prop.level
end

function EntityModel:getHeroAvatarParams()
    if not self:isHero() then return end
    local raceID = self.userBaseInfo.raceID
    -- 角色扮演 默认是自己的raceID，敌方是我方raceID+1
    if self.isRolePlay and not self:isInMyTeam() then
        raceID = raceID + 1
    end

    local ret = {}
    ret.classID = self.userBaseInfo.classID
    ret.raceID = raceID
    ret.gender = self.userBaseInfo.gender
    ret.hairID = self.userBaseInfo.hairID
    ret.faceID = self.userBaseInfo.faceID
    ret.hairColorID = self.userBaseInfo.hairColorID
    ret.fashionIDs = self.fashionIDs
    ret.bHero = self:isHero()
    ret.dir = self.dir

    return ret
end

function EntityModel:getNPCAvatarParams()
    if not self:isNpc() then return end
    local res = GD:queryNpcRes(self.protoUnit.npcId) or {}
    local name = res.dbRes or "harvestholem"
    local path = "armatures/characters/"..name.."/"
    local textureFile = (res.dbTexture and res.dbTexture or "texture")
    local skeleton = path.."skeleton"
    local texture = path..textureFile

    return skeleton, texture
end

function EntityModel:isHero()
    return self.kind == Enums.UnitType.Player or self.npcKind == Enums.NpcKind.NpcKind_Partner
end

function EntityModel:isNpc()
    return self.kind == Enums.UnitType.Npc and self.npcKind ~= Enums.NpcKind.NpcKind_Partner
end

function EntityModel:isPartner()
    return self.npcKind == Enums.NpcKind.NpcKind_Partner
end

function EntityModel:isBoss()
    if self:isNpc() then
        local npcRes = GD:queryNpcRes(self.protoUnit.npcId)
        if not npcRes then
            return false
        end
        return (npcRes.isBoss and tonumber(npcRes.isBoss)==1 or false)
    else
        return false
    end
end

function EntityModel:getDeathSound()
    if self:isHero() then
        local soundFile = GD:getPlayerDeathSound(self.userBaseInfo.classID, self.userBaseInfo.raceID, self.userBaseInfo.gender)
        return soundFile
    elseif self:isNpc() then
        return GD:getNpcDeathSound(self.protoUnit.npcId)
    else
        return nil
    end
end

function EntityModel:getSelectSize()
    if self:isHero() then
        return 100
    elseif self:isNpc() then
        return GD:getSelectSize(self.protoUnit.npcId)
    else
        return 100
    end
end

function EntityModel:getSelectExcursion()
    if self:isHero() then
        return 0
    elseif self:isNpc() then
        return GD:getSelectExcursion(self.protoUnit.npcId)
    else
        return 0
    end
end

function EntityModel:getSex()
    if self:isHero() then
        return self.userBaseInfo.gender
    else
        return nil
    end
end

function EntityModel:getIsShowMana()
    if self:isHero() then
        return true
    elseif self:isNpc() then
        return GD:getIsShowMana(self.protoUnit.npcId)
    else
        return false
    end
end

-- function EntityModel:isDead()
--     return not self:isAlive()
-- end

function EntityModel:getName()
    local name = self.name
    if self:isNpc() then
        local npcRes = GD:queryNpc(self.protoUnit.npcId)
        if npcRes then
            name = L(npcRes.name,name)
        end
    end
    return name
end

function EntityModel:getFaceSideIcon(callback)
    local iconPath
    if self:isNpc() then
        local npcRes = GD:queryNpcRes(self.protoUnit.npcId)
        if npcRes and npcRes.face then
            iconPath = Res.npcIconPath..npcRes.face..".png"
        end
    elseif self:isHero() then
        local params = {
            hairID=self.userBaseInfo.hairID,
            faceID=self.userBaseInfo.faceID,
            hairColorID = self.userBaseInfo.hairColorID,
            raceID = self.userBaseInfo.raceID
        }
        if self:isPartner() then
            iconPath = AvatarFactotry.getPartnerIconPath(params, function(path)
                if callback then
                    callback(path)
                end
            end)
        else
            iconPath = AvatarFactotry.getOrCreateHeroIconPath(params, function(path)
                if callback then
                    callback(path)
                end
            end)
        end
    end

    if callback then
        callback(iconPath)
    end
    return iconPath
end

function EntityModel:getFaceSideEnemyIcon(callback)
	--区分上面的函数，该函数与上述函数功能一致，区别在于获取敌方红色头像
	local iconPath
	
	--敌方不存在NPC概念
	--添加一条判断也可控制其他生物
	--if self:isNpc() then
	--	local npcRes = GD:queryNpcRes(self.protoUnit.npcId)
	--	if npcRes and npcRes.face then
	--		iconPath = Res.npcIconPath..npcRes.face..".png"
	--	end
	--else
	if self:isHero() then
        local params = {
            hairID=self.userBaseInfo.hairID,
            faceID=self.userBaseInfo.faceID,
            hairColorID = self.userBaseInfo.hairColorID,
            raceID = self.userBaseInfo.raceID
        }
        if self:isPartner() then
            iconPath = AvatarFactotry.getPartnerIconPath(params, function(path)
                if callback then
                    callback(path)
                end
            end)
        else
            iconPath = AvatarFactotry.getOrCreateEnemyHeroIconPath(params)
            iconPath = iconPath or AvatarFactotry.getOrCreateHeroIconPath(params, function(path)
                if callback then
                    callback(path)
                end
            end)
        end
	end
	
    if callback then
		callback(iconPath)
	end
	
	return iconPath
end

function EntityModel:getNpcId()
    if self:isNpc() then
        return self.protoUnit.npcId
    end
    return nil
end

function EntityModel:getNpcKind()
    if self:isNpc() then
        return self.npcKind
    end
    return nil
end

function EntityModel:getClassName()
    if self:isHero() then
        local classId = self:getClassId()
        if classId then
            local className = GD:queryClass(classId).string
            if className then
                return L(className)
            end
        end
    elseif self:isNpc() then
        local npcConfig = GD:queryNpc(self.protoUnit.npcId)
        local npcType = (npcConfig and npcConfig.type or 1)
        local npcName = L(Enums.NpcTypeName[tonumber(npcType)])
        return npcName
    end

    return nil
end

function EntityModel:getClassId()
    return tonumber(self.userBaseInfo.classID)
end

function EntityModel:getClassIcon(classId)
    local classIcon = GD:queryClass(classId).icon2
    if classIcon then
        classIcon = Res.classIconPath..classIcon..".png"
    end
    return classIcon
end

function EntityModel:isLeft()
    --dir为1面朝右，头像在左侧
    return self.dir == 1
end

function EntityModel:getControlledSkills()
    local controllSkills = {}
    local skillCfg
    for _, v in pairs(self.skills) do
        skillCfg = v.skillCfg
        if skillCfg
          and not skillCfg:isBasicAttack()
          and not skillCfg:isRollSkill()
          and not skillCfg:isLegendSkill() then
            table.insert(controllSkills, v)
        end
    end
    return controllSkills
end

function EntityModel:getNormalSkill()
    local skillCfg
    for _, v in pairs(self.skills) do
        skillCfg = v.skillCfg
        if skillCfg and skillCfg:isBasicAttack() then
            return v
        end
    end
    return nil
end

function EntityModel:getRollSkill()
    local skillCfg
    for _, v in pairs(self.skills) do
        skillCfg = v.skillCfg
        if skillCfg and skillCfg:isRollSkill() then
            return v
        end
    end
    return nil
end

function EntityModel:getLegendSkill()
    local skillCfg
    for _, v in pairs(self.skills) do
        skillCfg = v.skillCfg
        if skillCfg and skillCfg:isLegendSkill() then
            return v
        end
    end
    return nil
end

function EntityModel:getBasicSkillId()
    local skillCfg
    for _,v in pairs(self.skills) do
        skillCfg = v.skillCfg
        if skillCfg and skillCfg:isBasicAttack() then
            return skillCfg:getId()
        end
    end
    return nil
end

function EntityModel:getSfxPath()
    if self:isHero() then
        local sex = self.userBaseInfo.gender or Enums.Sex.female
        local race = self.userBaseInfo.raceID or 1

        local path = "sfx/avata/"..Enums.SexFileStr[sex].."/"..tostring(race)
        return path
    elseif self:isNpc() then
         return GD:getNpcSfxPath(self.protoUnit.npcId)
    else
         return nil
    end
end

function EntityModel:getSfxFilePath(fileName)
    if fileName then
        local path
        local fileExist
        if self.sfxPath then
            local sfxPath = self.sfxPath
            local strArray = string.split(sfxPath,"/")
            local len = #strArray
            path = sfxPath.."/"..fileName
            fileExist = FileUtils_isFileExist(FileUtils,path)
            while (len > 0 and not fileExist) do
                path = table.concat( strArray, "/").."/"..fileName
                fileExist = FileUtils_isFileExist(FileUtils,path)
                if fileExist then
                    break
                else
                    table.remove(strArray,#strArray)
                    len = #strArray
                end
            end

        else
            path = "sfx/"..fileName
            fileExist = FileUtils_isFileExist(FileUtils,path)
        end

        if fileExist then
            return path
        else
            return nil
        end
    end
    return nil
end

function EntityModel:setSkills(skills)
    self.skills = skills
end

function EntityModel:setId(id)
    self.id = id
end

function EntityModel:setDir(dir)
    self.dir = dir
end

function EntityModel:setTeamId(teamId)
    self.teamId = teamId
end

function EntityModel:setIsSummonEntity(flag)
    self.isSummonEntity = flag
end

function EntityModel:setIsRefreshEntity(flag)
    self.isRefreshEntity = flag
end

function EntityModel:setIsFakeNpc(flag)
    self.isFakeNpc = flag
end

function EntityModel:setCanRevive(flag)
    self.canRevive = flag
end

function EntityModel:getCanRevive()
    return self.canRevive
end

function EntityModel:setDefaultZOrder(zorder)
    self.defaultZOrder = zorder
end

function EntityModel:setSize(size)
    self.size = size
end

function EntityModel:setHeight(height)
    self.height = height
end

return EntityModel
